<?php

abstract class Base_Model
{
    protected $form     = null;
    
    protected $_dbTable  = null;
    
    protected $_fields   = array();
	protected $_entries  = array();
	
    protected $_property = array();


    public function __construct(array $data = null)
    {
        $this->init();
        
        if (is_array($data)) {
            $this->setEntry($data);
        }
    }
    
    public function init()
    {
    }
    
    /**
     * Singleton instance
     *
     * @return Base_Db_Table
     */
    public function getDbTable()
    {
        if (null === $this->_dbTable) {
            $this->_dbTable = new $this->_tableName();
        }

        return $this->_dbTable;
    }
    
	public function makeByForm(Base_Form $form)
	{
        $this->form = $form;
        $this->setEntry($this->form->getValues());
        $this->filterEntry();
        return $this;
	}
	
	public function readBy($key, $val)
	{
        $resultRow = $this->getDbTable()->readBy($key, $val);
        if (!$resultRow) {
            throw new Base_Model_Exception(
               'Model not exist', 404
            );
        }
        
        $this->setEntry($resultRow);
        return $this;
	}
	
	public function read($id)
	{
        $resultRow = $this->getDbTable()->read($id);
        if (!$resultRow) {
            throw new Base_Model_Exception(
               'Model not exist', 404
            );
        }
        
        $this->setEntry($resultRow->toArray());
        return $this;
	}
	
	public function save()
	{
        if (in_array('created', $this->_fields)) {
            if (null == $this->{$this->getDbTable()->getPrimary()}) {
                $this->created = time();
            } else {
                unset ($this->created);
                if (in_array('changed', $this->_fields)) {
                    $this->changed = time();
                }
            }
        }
        
        return $this->getDbTable()
                    ->save($this);
	}
	
	public function drop()
	{
        return $this->getDbTable()
                    ->drop($this);
	}

    protected function setEntry(array $data)
    {
        //save field
		foreach ($data as $field=> $value) {
            if (in_array($field, $this->_fields)) {
                $this->_entries[$field] = $value;
            }
		}
		return $this;
    }
    
    protected function filterEntry()
    {
		//filter field
		foreach ($this->_entries as $key=> $value) {
            $method = 'filter'. ucfirst($key);
            if (method_exists($this, $method)) {
                $this->$method();
            }
        }
    }

    public function setProperty($name, $value)
    {
        if (!isset($this->_property[$name])) {
            $this->_property[$name] = $value;
        }
        return $this;
    }
    
    public function getProperty($name)
    {
        return $this->_property[$name];
    }
    
    public function issetProperty($name)
    {
        return isset ($this->_property[$name]);
    }
    
    public function __set($key, $value)
    {
		if (!in_array($key, $this->_fields)) {
			trigger_error(__METHOD__ ." the field: '$key' can not set", E_USER_NOTICE);
		}
		
        if (method_exists($this, 'filter'. ucfirst($key))) {
            $action = 'filter'. ucfirst($key);
            $value = $this->$action($value);
        }
		$this->_entries[$key] = $value;
		return $this;
    }

    public function __get($key)
    {
		if (array_key_exists($key, $this->_entries)) {
            return $this->_entries[$key];
		}
    }
    
    public function __unset($key)
    {
		if (!in_array($key, $this->_fields)) {
			trigger_error(__METHOD__ ." the field: '$key' can not set", E_USER_NOTICE);
		}
		
		unset ($this->_entries[$key]);
		return $this;
    }
    
    public function __isset($key)
    {
		if (!in_array($key, $this->_fields)) {
			trigger_error(__METHOD__ ." the field: '$key' can not set", E_USER_NOTICE);
		}
		
		return isset ($this->_entries[$key]);
    }
    
    public function toArray()
    {
		return $this->_entries;
	}
}